import turtle as tl
import numpy as np
import time

"""
Ref:
    The Beauty of Bézier Curves https://www.youtube.com/watch?v=aVwxzDHniEw
"""

P = np.array([[-200, -200], [-240, 240], [260, 230], [260, -220]])


class Point(tl.Turtle):
    def __init__(self, p, cl="blue"):
        tl.Turtle.__init__(self, shape="circle", visible=False)
        self.penup()
        self.color(cl)
        self.setpos(p[0], p[1])
        self.showturtle()

class Line(tl.Turtle):
    def __init__(self, p1, p2, cl="black"):
        tl.Turtle.__init__(self, shape="circle", visible=False)
        self.penup()
        self.color(cl)
        self.setpos(p1[0], p1[1])
        self.pendown()
        self.goto(p2[0], p2[1])
        self.hideturtle()

    def setPoint(self, p1, p2):
        self.clear()
        self.penup()
        self.setpos(p1[0], p1[1])
        self.pendown()
        self.goto(p2[0], p2[1])
        self.penup()

def draw():
    tl.hideturtle()
    tl.speed(1)
    tl.tracer(2, 8)

    for p_ in P:
        p = Point(p_, "red")

    for i in range(len(P)-1):
        l = Line(P[i], P[i+1])

    time.sleep(2)

    arrP = []
    for i in range(6):
        p = Point(P[0], "blue")
        p.shapesize(0.5, 0.5)
        arrP.append(p)

    arrP[-1].color("purple")

    arrL = []
    for i in range(3):
        arrL.append(Line(P[0], P[1], 'gray'))

    # Bezier Curve points
    bc = tl.Turtle()
    bc.hideturtle()
    bc.penup()
    bc.color("purple")
    bc.goto(P[0][0], P[0][0])
    bc.pendown()

    # calculate/draw point A, B, C, D, E, F
    nseg = 400
    for t_ in range(nseg + 1):
        t = t_ / nseg

        A = P[0] * (1 - t) + P[1] * t
        B = P[1] * (1 - t) + P[2] * t
        C = P[2] * (1 - t) + P[3] * t
        D = A * (1 - t) + B * t
        E = B * (1 - t) + C * t
        F = D * (1 - t) + E * t

        arrP[0].setpos(A[0], A[1])
        arrP[1].setpos(B[0], B[1])
        arrP[2].setpos(C[0], C[1])
        arrP[3].setpos(D[0], D[1])
        arrP[4].setpos(E[0], E[1])
        arrP[5].setpos(F[0], F[1])

        arrL[0].setPoint(A, B)
        arrL[1].setPoint(B, C)
        arrL[2].setPoint(D, E)

        bc.goto(F[0], F[1])


if __name__ == "__main__":
    draw()

    tl.mainloop()


